home *** CD-ROM | disk | FTP | other *** search
File List | 1989-12-13 | 10.6 KB | 438 lines |
- _DISCRETE EVENT SIMULATION IN CONCURRENT C_
- by Narain Gehani and W.D. Roome
-
- [LISTING ONE]
-
- File: sim-sched.h
-
- process spec sched() {
- trans long now() /* return simulated time */
- trans long reqDelay(long del);
- /* request delay */
- trans long wait(long x); /* wait for delay */
- trans void addUser(); /* add client */
- trans void dropUser(); /* drop client */
- trans void passive(); /* client is passive */
- trans void active(); /* client is active */
- };
-
-
- [LISTING TWO]
-
- File: sim-source.h
-
- process spec source(
- process sched s, /* scheduler */
- process queue outQ, /* output queue */
- long meanIat, /* mean inter-arrival time */
- long meanServt, /* mean service time */
- long nGen, /* number to generate */
- name_t name); /* symbolic name */
-
-
- [LISTING THREE]
-
- File: sim-server.h
-
- process spec server (
- process sched s, /* scheduler */
- process queue inQ, /* input queue */
- process queue outQ, /* output queue */
- double speed, /* speed of server */
- name_t name); /* symbolic name */
-
-
- [LISTING FOUR]
-
- File: sim-qItem.h
-
- typedef struct {
- /* Public: */
- long servt; /* service time for job */
- long arrive; /* time job arrived */
-
- /* Private to queue process: */
- long qEnter; /* time entered queue */
- int ticket; /* ticket from takeReq */
- int gotItem; /* !=0 if item was taken */
- } qItem;
-
-
- [LISTING FIVE]
-
- File: sim-queue.h
-
- process spec queue(
- process sched s, /* scheduler */
- int maxSize, /* max queue size */
- name_t name) /* symbolic name */
- {
- trans int itemCnt(); /* return queue size */
- trans void addProd(); /* add producer */
- trans void dropProd(); /* drop producer */
- trans void addCons(); /* add consumer */
- trans void dropCons(); /* drop consumer */
-
- /* start and finish put request:*/
- trans int putReq(qItem);
- trans void putWait(int, qItem);
-
- /* start and finish take request:*/
- trans qItem takeReq();
- trans qItem takeWait(int);
- };
-
- [LISTING SIX]
-
- File: sim-stats.h
-
- typedef struct {
- long nv; /* number of values */
- long maxv; /* max value */
- double sumv; /* sum of values */
- double sumsq; /* sum of squares */
- } stats;
-
- void stInit(); /* initialize structure */
- void stVal(); /* add new value */
- double stMean(); /* return mean value */
- double stSdev(); /* return standard deviation */
- long erand(); /* exponential random number */
-
-
-
- [LISTING SEVEN]
-
- File: sim-main.cc
-
- name_t makeName(name) char *name;
- { name_t ret;
- strcpy(ret.str, name);
- return ret;
- }
-
- main()
- { process sched s;
- process queue q1, q2;
- long nGen=100000; /* number of jobs */
- long servt=500; /* mean service time */
- long iat=1000; /* mean inter-arrival */
-
- /* Create virtual time scheduler. */
- s = create sched(); s.addUser();
-
- /* Create queues and servers. */
- q1 = create queue(s, 100, makeName("Q1"));
- q2 = create queue(s, 100, makeName("Q2"));
- create source(s, q1, iat, servt, nGen,
- makeName("Src"));
- create server(s, q1, q2, 0.5,
- makename("Serv1.1"));
- create server(s, q1, q2, 0.5,
- makename("Serv1.2"));
- create server(s, q2, c_nullpid, 1.0,
- makename("Serv2"));
-
- /* Wait for all processes to start. */
- delay 2.0; s.dropUser();
- }
-
-
-
- [LISTING EIGHT]
-
- File: si-source.cc
-
- process body source(s, outQ, meanIat,
- meanServt, nGen, name)
- { stats iat, servt;
- qItem item;
- long i, t;
-
- /* Initialization phase */
- s.addUser();
- outQ.addProd();
- stInit(&iat); stInit(&servt);
-
- /* Main processing phase: generate jobs. */
- for (i=1; i <= nGen; i++) {
- t = erand(meanIat);
- stVal(&iat, t);
- item.arrive = s.wait(s.reqDelay(t));
- item.servt = erand(meanServt);
- stVal(&servt, item.servt);
- qPut(outQ, item);
- }
- /* Termination phase: print stats, etc. */
- print statistics;
- outQ.dropProd(); s.dropUser();
- }
-
-
-
- [LISTING NINE]
-
- File: sim-server.cc
-
- process body server(s, inQ, outQ, speed, name)
- { stats sysTime; /* time-in-system */
- qItem item;
- long ts;
-
- s.addUser(); stInit(&sysTime);
- inQ.addCons();
- if (outQ != c_nullpid)
- outQ.addProd();
-
- while (qTake(inQ, &item)) {
- ts = s.wait(s.reqDelay(item.servt/speed));
- stVal(&sysTime, ts - item.arrive);
- if (outQ != c_nullpid)
- qPut(outQ, item);
- }
-
- print statistics;
- if (outQ != c_nullpid)
- outQ.dropProd();
- inQ.addCons(); s.dropUser();
- }
-
- [LISTING TEN]
-
- File sim-qPut.cc
-
- /* Put item onto queue; wait if full. */
- void qPut(q, item)
- process queue q; qItem item;
- { int ticket = q.putReq(item);
- if (ticket >= 0)
- q.putWait(ticket, item);
- }
-
- /* Set *itemp to next item; wait if empty. */
- /* Return 1 if item was taken, 0 on EOF */
- int qTake(q, itemp)
- process queue q; qItem *itemp;
- {
- *itemp = q.takeReq();
- if (itemp->ticket >= 0)
- *itemp = q.takeWait(itemp->ticket);
- return itemp->gotItem;
- }
-
- [LISTING ELEVEN]
-
- File: sim-qInfo.h
-
- /* *tInfo: Describe outstanding tickets. */
- typedef struct {
- int acc; /* next ticket to accept */
- int give; /* next ticket to give out */
- int nPass; /* pending passive clients */
- } tInfo;
-
- /* qInfo: Describe one queue. */
- typedef struct {
- process sched s; /* scheduler process */
- int max; /* max queue size */
- int nProd; /* number of producers */
- int nCons; /* number of consumers */
- name_t name; /* name of queue */
- stats qTime; /* time-in-queue stats */
- stats qSize; /* for queue size stats */
- int nElem; /* items in queue */
- int head; /* index head of queue */
- int tail; /* index tail of queue */
- qItem *items; /* alloc'd array of items */
-
- /* Describe pending put, take requests: */
- tInfo pPut, pTake;
- } qInfo;
-
-
- [LISTING TWELVE]
-
- File: sim-queue.cc
-
- process body queue(s, maxSize, name)
- { qInfo q; qItem x;
- initialize qInfo structure;
- accept addProd() { q.nProd++; }
-
- while (q.nProd+q.nCons >0) {
- select {
- (q.nElem<q.max && q.pPut.acc==q.pPut.give):
- accept putReq(item)
- { putItem(&q, &item); treturn -1; }
- or (q.nElem==q.max):
- accept putReq(item)
- { s.passive(); q.pPut.nPass++;
- treturn incTick(&q.pPut.give); }
- or (q.nElem<q.max):
- accept putWait(qt, item)
- suchthat (qt == q.pPut.acc)
- { putItem(&q, &item);
- incTick(&q.pPut.acc); }
- or (q.nElem>0 && q.pTake.acc==q.pTake.give):
- accept takeReq()
- { treturn takeItem(&q); }
- or (q.nElem==0):
- accept takeReq()
- { x.ticket = incTick(&q.pTake.give);
- s.passive(); q.pTake.nPass++;
- treturn x; }
- or (q.nElem>0):
- accept takeWait(qt)
- suchthat (qt == q.pTake.acc)
- { incTick (&q.pTake.acc);
- treturn takeItem(&q); }
- or (q.nProd==0 && q.nElem==0):
- accept takeWait(qt)
- { x.gotItem = 0; treturn x; }
-
- or accept itemCnt() { treturn q.nElem; }
- or accept addCons() { q.nCons++; }
- or accept addProd() { q.nProd++; }
- or accept dropCons() { q.nCons--; }
- or accept dropProd() { q.nProd--; }
- }
- /* On EOF, make pending takers active. */
- if (q.nProd==0 && q.nElem==0)
- for (; q.pTake.nPass > 0; q.pTake.nPass--)
- s.active();
- }
- print statistics;
- }
-
- [LISTING THIRTEEN]
-
- File: sim-qAux.cc
-
- /* Increment ticket, return prev value. */
- int incTick(tp)
- int *tp;
- { int t = *tp;
- *tp = (t+1)%10000;
- return t;
- }
-
- /* Remove and eturn the next item in the queue. */
- qItem takeItem(qp)
- qInfo *qp;
- {
- qItem item;
- item = qp->items[qp->head];
- item.ticket = -1;
- item.gotItem = 1;
- stVal(&qp->qTime, qp->s.now() - item.qEnter);
- qp->nElem--;
- qp->head = (qp->head+1) % qp->max;
- if (qp-pPut.nPass >0)
- { qp->s.active(); qp->pPut.nPass--; }
- return item;
- }
-
- /* Add item *itemp to queue. */
- void putItem(qp, itemp)
- qInfo *qp; qItem *itemp;
- {
- qp->items[qp->tail] = *itemp;
- qp->items[qp->tail].qEnter = qp->s.now();
- stVal(&qp->qSize, qp->nElem);
- qp->nElem++;
- qp->tail = (qp->tail+1) % qp->max;
- if (qp->pTake.nPass > 0)
- { qp-<>s.active(); qp->pTake.nPass--; }
- }
-
- [LISTING FOURTEEN]
-
- File: sim-sched.cc
-
- process body sched()
- { int nUser, nAct, i;
- long curTime = 0; /* Current simulated time */
- ordered list of pending delay requests;
-
- initialize pending delay list data structures;
- accept addUser() { nUser = nAct = 1; }
- while (nUser >0) {
- select {
- accept addUser() { ++nUser; ++nAct; }
- or accept dropUser() { --nUser; --nAct; }
- or accept active() { ++nAct; }
- or accept passive() { --nAct; }
- or accept now() { treturn curTime; }
- or accept reqDelay(x)
- { add request for curTime+x to pending delay list;
- nAct--; treturn request-index; }
- }
- if (nAct == 0 && pending delay list is not empty) {
- curTime = time of request at head of list;
- nAct = number of processes waiting for that time;
- for (i = 1; i <= nAct; i++)
- accept wait(x)
- suchthat (x == index-of-head-request)
- { treturn curTime; }
- discard request at head of pending delay list;
- }
- }
- }
-
- Example 1: The Server Process
-
- while (1) {
- delay for random inter-arrival time;
- generate item;
- call queue process to put item in queue;
- }
-
- Example 2: Moving Jobs Between Queues
-
- qItem item;
- process queue qFrom, qTo;
-
- while (qTake(qFrom, &item))
- qput(qTo, item);
-
-
-
- Example 3: Generating Random Numbers
-
- stats mystats;
- int i;
-
- stInit(&mystats);
- for (i = 1; i <= 10000; i++)
- stVal(&mystats, erand(100));
- printf("Mean is %lf\n", stMean(&mystats));
-
-
- Example 4: Choosing Queues
-
-
- if (outQ1.itemCnt() < outQ2.itemCnt())
- qPut(outQ1, item);
- else
- qPut(outQ2, item);
-
-
- Example 5: An Example of main()
-
- main()
- {
- create all processes
- while (1) {
- s.wait(s.reqDelay(10000));
- for each entity process p
- entity-stats = p.giveStats();
- if (statistics have been stable for long enough)
- break;
- }
- print final statistics
- for all processes p
- c_abort(p);
- }
-
-